<?php
/**
 * 公共函数库 - JBlog
 * 
 * @copyright (c) 2008-2010 JBlog (www.lisijie.org)
 * @author lisijie <lisijie86@gmail.com>
 * @version $Id: func_global.php 545 2010-07-20 10:07:57Z lisijie86 $
*/

!defined('IN_JBLOG') && exit('Access Denied!');

/**
 * GBK to UTF-8
 *
 * @param string $string 
 * @return string
 */
function gb2utf8($string) {
	if ( function_exists('iconv') ) {
		return iconv('gbk', 'utf-8//IGNORE', $string);
	}
	if ( function_exists('mb_convert_encoding') ) {
		return mb_convert_encoding($string, 'utf-8', 'gbk');
	}
	return $string;
}

//过滤ID数组中的非法数据
function filter_ids(& $array) {
	foreach ( (array)$array as $key => $val ) {
		if ( !is_numeric($val) ) {
			unset($array[$key]);
		}
	}
}

function my_htmlspecialchars($string) {
	if ( is_string($string) ) {
		return htmlspecialchars($string, ENT_QUOTES);
	} elseif ( is_array($string) ) {
		foreach ( $string as $key => $value ) {
			$string[$key] = my_htmlspecialchars($value);
		}
	}
	return $string;
}

//调用gravatar头像
function avatar($email, $size = 32, $rating = 'G', $output = true) {
	$grav_rating = array("G", "PG", "R", "X");
	!in_array($rating, $grav_rating) && $rating = 'G';
	$default = config('blogurl').'/images/avatar.gif';
	$grav_url = "http://www.gravatar.com/avatar.php?gravatar_id=".md5($email)."&amp;raging=".$rating."&amp;default=".urlencode($default)."&amp;size=".$size;
	$str = '<img src="'.$grav_url.'" width="'.$size.'" class="avatar" alt="avatar" />';
	if ($output) {
		echo $str;
	} else {
		return $str;
	}
}

/**
 * 生成URL地址
 *
 * @param string $query 普通URL查询字符串
 * @param array $params 附加参数
 * @return string
 */
function url($query) {
	global $rewrite;
	return $rewrite->url($query);
}

/**
 * 计算程序执行时间，单位：秒
 * 
 * @param int $precision 精确度
 * @return float 执行时间/秒 
 */
function exec_time($precision = 5) {
	global $starttime;
	$endtime = explode(' ', microtime());
	return round(($endtime[0] + $endtime[1]) - $starttime, $precision);
}

/**
 * ajax输出，输出格式为JSON
 *
 * @param array $array
 * @return void
 */
function ajax_out($array) {
	obclean();
	@header("Content-Type: text/html; charset=".JBLOG_CHARSET);
	exit(json_encode($array));
}

/**
 * 数组元素串接
 *
 * 将数组的每个元素用逗号连接起来，并给每个元素添加单引号，用于SQL语句中串接ID
 * @param array $array
 * @return string
 */
function simplode($array) {
	return "'".implode("','", $array)."'";
}

/**
 * 链接跳转
 *
 * @param string $url
 * @return void
 */
function redirect($url) {
	if ( !headers_sent() ) {
		header("HTTP/1.1 301 Moved Permanently");
		header('Location: '.$url);
	} else {
		echo '<script type="text/javascript">';
		echo 'window.location.href="'.$url.'";';
		echo '</script>';
		echo '<noscript>';
		echo '<meta http-equiv="refresh" content="0;url='.$url.'" />';
		echo '</noscript>';
   }
}

/**
 * 格式化时间
 *
 * @param int $timestamp 时间戳，默认为当前时间戳
 * @param string $format 格式化时间格式
 * @return string 返回格式化后的时间
 */
function get_date($timestamp = NOW, $format = '') {
	$timezone = config('timezone');
	if ( empty($format) ) $format = config('timeformat');
	if ( empty($format) ) $format = 'Y-m-d H:i:s'; 
	return gmdate($format, $timestamp + intval($timezone) * 3600);
}

/**
 * 时间字符串转换为时间戳
 *
 * @param string $timestr 表示时间的字符串
 * @return int 时间戳
 */
function str_to_time($timestr) {
	$timezone = config('blog','timezone');
	return function_exists('date_default_timezone_set') ? (strtotime($timestr) - 3600 * $timezone) : strtotime($timestr);
}

/**
 * 获取/设置一个配置项
 *
 * 只有$key参数时为获取值，传递第二个参数时为赋值
 * 
 * @param string $key 键名
 */
function config($key) {
	global $_CACHE, $db;
	if ( !is_string($key) ) return ;
	if ( func_num_args() == 1 ) {
		if ( isset($_CACHE['config'][$key]) ) {
			return $_CACHE['config'][$key];
		}
		if ( $option = $db->fetch_one_array("SELECT `value` FROM ".tname('config')." WHERE `name` = '".addslashes($key)."'") ){
			$_CACHE['config'][$key] = $option['value'];
			return $option['value'];
		}
		return false;
	} else {
		$_CACHE['config'][$key] = func_get_arg(1);
		$db->insert('config', array('name'=>$key, 'value'=>func_get_arg(1)), TRUE);
		require_once JBLOG_INC.'func_cache.php';
		recache('config');
	}
}

/**
 * 返回包含前缀的JBLOG表名
 *
 * @param string $table 表名
 * @return string 
 */
function tname($table) {
	return DB_TABLEPRE.$table;
}

/**
 * 创建目录
 * 
 * 支持创建多级目录，目录权限为777，并在目录下生成名为index.html的空文件
 * @param string $path 路径
 * @return boolean 成功返回true,目录已存在或不合法返回false
 */
function make_dir($path) {
	if ( is_dir($path) || strpos($path, '..')!==false ) return FALSE;
	$path = str_replace(JBLOG_ROOT, '', $path);
	$dirs = explode('/', $path);
	$basepath = JBLOG_ROOT;
	foreach ($dirs as $dir) {
		$basepath .= $dir.'/';
		if ( !is_dir($basepath) ) {
			@mkdir($basepath);
			@fopen($basepath.'index.html','wb');
			@chmod($basepath, 0777);
		}
	}
	return TRUE;
}

/**
 * 递归删除整个目录
 * 
 * @param string $path 要删除的目录
 * @return void
 */
function remove_dir($path) {
	$path = rtrim($path, '/');
	if ( $handle = opendir($path) ) {
		while ( false !== ($d = readdir($handle)) ) {
			if ( $d != '.' && $d != '..' ) {
				if ( is_dir($path.'/'.$d) ) {
					remove_dir($path.'/'.$d);
				} else {
					@unlink($path.'/'.$d);
				}
			}
		}
		closedir($handle);
		@rmdir($path);
	}
}

/**
 * 获取客户端的真实IP地址
 *
 * @return string IP地址
 */
function get_onlineip() {
	if ($_SERVER['HTTP_X_FORWARDED_FOR']) {
		$onlineip = $_SERVER['HTTP_X_FORWARDED_FOR'];
	} elseif ($_SERVER['HTTP_CLIENT_IP']) {
		$onlineip = $_SERVER['HTTP_CLIENT_IP'];
	} else {
		$onlineip = $_SERVER['REMOTE_ADDR'];
	}
	return preg_match("/^([0-9]{1,3}\.){3}[0-9]{1,3}$/",$onlineip) ? $onlineip : 'unknown';	
}

/**
 * 为特殊字符加上反斜杠
 * 
 * 与addslashes不同之处在于本函数支持数组
 * @param string|array $string
 * @return string|array 返回处理后的变量
 */
function add_slashes($string) {
	if (!is_array($string)) return addslashes($string);
	foreach ($string as $key => $val) {
		$string[$key] = add_slashes($val);
	}
	return $string;
}

/**
 * 去除特殊字符的反斜杠
 * 
 * 与stripslashes不同之处在于本函数支持数组
 * @param string|array $string
 * @return string|array 返回处理后的变量
 */
function del_slashes($string) {
	if (!is_array($string)) return stripslashes($string);
	foreach ($string as $key => $val) {
		$string[$key] = del_slashes($val);
	}
	return $string;
}

//ob_start
function obstart() {
	if ( config('obstart') && function_exists('ob_gzhandler') ) {
		ob_start('ob_gzhandler');
	} else {
		ob_start();
	}
}
//ob_end_clean
function obclean() {
	ob_end_clean();
	obstart();
}

//是否需要缓存页面
function cache_page() {
	global $_USER,$get;
	if ( !$_USER['id'] && config('cachepage') && in_array($get['mod'], config('cachemode')) ) {
		return true;
	}
	return false;
}

//页尾处理
function footer() {
	global $get;
	$output = ob_get_contents();
	obclean();
	if ( cache_page() ) {
		require_once JBLOG_INC.'class_cachepage.php';
		$cache = new CachePage();
		$cache->set($get,$output);
	}
	echo $output;
	unset($output);
	if ( DEBUG ) {
		global $_DEBUG;
		//!is_dir(DATA_ROOT.'debug') && make_dir(JBLOG_ROOT.'debug');
		//file_put_contents(get_date(NOW,'m-d H:i:s').'.txt', );
	}
	exit;
}

//检查提交
function check_submit() {
	if (isset($_POST['dosubmit']) && $_SERVER['REQUEST_METHOD'] == 'POST' && (empty($_SERVER['HTTP_REFERER']) || strpos($_SERVER['HTTP_REFERER'], 'http://'.$_SERVER['HTTP_HOST']) === 0) ) {
		return true;
	}
	return false;
}

//字符串过滤
function check_str($string, $isurl = false) {
	$string = preg_replace('/[\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F]/','',$string);
	$string = str_replace(array("\0","%00","\r"),'',$string);
	empty($isurl) && $string = preg_replace("/&(?!(#[0-9]+|[a-z]+);)/si",'&amp;',$string);
	$string = str_replace(array("%3C",'<'),'&lt;',$string);
	$string = str_replace(array("%3E",'>'),'&gt;',$string);
	$string = str_replace(array('"',"'","\t",'  '),array('&quot;','&#39;','    ','&nbsp;&nbsp;'),$string);
	return trim($string);
}

//是否创始人
function is_founder($userid = 0) {
	global $_USER;
	!$userid && $userid = $_USER['id'];
	if ( $userid == 1 ) {
		return TRUE;
	}
	return FALSE;
}

//是否管理员
function is_admin() {
	global $_USER;
	if ( is_founder() || $_USER['group'] == 'admin' ) {
		return true;
	}
	return false;
}

/**
 * 检查权限
 * 
 * @param string $type 权限类型
 * @param string $key 具体权限
 * @param string $except 排除用户组
 */
function check_perm($type,$key='',$except='') {
	global $_USER;
	if ( $type == 'comment' && is_admin() ) {
		if ( $key == 'post' ) {
			return true;
		} elseif ( in_array($key, array('needcheck','seccode','timelimit','maxchar')) ) {
			return false;
		}
	} 
	if ( is_founder() ) return true;
	if ( !empty($except) && $_USER['group'] == $except ) return true;
	if ( $key == '' ) {
		return (isset($_USER['permission'][$type]) && !empty($_USER['permission'][$type]));
	}
	if ( isset($_USER['permission'][$type][$key]) && $_USER['permission'][$type][$key] == 1 ) {
		return true;
	}
	return false;
}

/**
 * 设置一个COOKIE
 *
 * @param string $var cookie变量名
 * @param string $val cookie值
 * @param int $expire 多少秒后失效，默认为0，即关闭浏览器后失效
 * @return bool
 */
function set_cookie($var, $val = '', $expire = 0) {
	$expire = $expire > 0 ? NOW + $expire : (empty($val) ? (NOW - 3600) : 0);
	$s = $_SERVER['SERVER_PORT'] == 443 ? 1 : 0;
	return setcookie(md5(COOKIE_PRE.$var), $val, $expire, COOKIE_PATH, COOKIE_DOMAIN, $s);
}

/**
 * 获取一个COOKIE值
 *
 * @param string $var cookie变量名
 * @return string cookie值，如果不存在则返回false
 */
function get_cookie($var) {
	$var = md5(COOKIE_PRE.$var);
	return isset($_COOKIE[$var]) ? $_COOKIE[$var] : False;
}

//字符串截取
function cut_str($str, $len = 0, $dot = '...',$encoding = 'utf-8') {
	if (!$len || strlen($str) <= $len) return $str;
	$tempstr = '';
	$str = str_replace(array('&amp;', '&quot;', '&lt;', '&gt;'), array('&', '"', '<', '>'), $str);
	if ($encoding == 'utf-8') {
		$n = $tn = $noc = 0;
		while($n < strlen($str)) {
			$t = ord($str[$n]);
			if($t == 9 || $t == 10 || (32 <= $t && $t <= 126)) {
				$tn = 1; $n++; $noc++;
			} elseif (194 <= $t && $t <= 223) {
				$tn = 2; $n += 2; $noc += 2;
			} elseif (224 <= $t && $t < 239) {
				$tn = 3; $n += 3; $noc += 2;
			} elseif (240 <= $t && $t <= 247) {
				$tn = 4; $n += 4; $noc += 2;
			} elseif (248 <= $t && $t <= 251) {
				$tn = 5; $n += 5; $noc += 2;
			} elseif ($t == 252 || $t == 253) {
				$tn = 6; $n += 6; $noc += 2;
			} else {
				$n++;
			}
			if($noc >= $len) {
				break;
			}
		}
		if($noc > $len) {
			$n -= $tn;
		}
		$tempstr = substr($str, 0, $n);
	} elseif ($encoding == 'gbk') {
		for ($i=0; $i<$len; $i++) {
			$tempstr .= ord($str{$i}) > 127 ? $str{$i}.$str{++$i} : $str{$i};
		}
	}
	$tempstr = str_replace(array('&', '"', '<', '>'), array('&amp;', '&quot;', '&lt;', '&gt;'), $tempstr);
	return $tempstr.$dot;
}

//数据大小单位转换
function sizecount($byte) {
	if ($byte < 1024) {
		return $byte.'B';
	} elseif (($size = round($byte/1024,2)) < 1024) {
		return $size.'KB';
	} elseif (($size = round($byte / (1024*1024),2)) < 1024) {
		return $size.'MB';
	} else {
		return round($byte / (1024*1024*1024),2).'GB';
	}
}

//获取$_GET或$_POST值
function getGP($var, $method = 'GP', $type = 'string') {
	if ($method == 'G' || $method != 'P' && isset($_GET[$var])) {
		$gp = &$_GET;
	} else {
		$gp = &$_POST;
	}
	if ($type == 'int') {
		return isset($gp[$var]) ? intval($gp[$var]) : 0;
	} elseif ($type == 'array') {
		return isset($gp[$var]) ? (array)$gp[$var] : array();
	} else {
		return isset($gp[$var]) ? (string)trim($gp[$var]) : '';
	}
}

//初始化GP值为变量
function initGP($keys, $method = 'GP', $type = 'string') {
	!is_array($keys) && $keys = array($keys);
	foreach ($keys as $key) {
		$GLOBALS[$key] = getGP($key, $method, $type);
	}
}

//提示信息
function show_msg ($message = '', $jumpurl = '', $refreshtime = 3) {
	global $_USER;
	obclean();
	$refreshtime && $refreshtime *= 1000;
	if ( empty($jumpurl) ) {
		$jumpurl = $_USER['refer'] ? $_USER['refer'] : config('blogurl');
	}
	$message .= '<script>setTimeout("window.location.href=\''.$jumpurl.'\'", "'.$refreshtime.'")</script>';
	$message_title = __('JBlog 提示信息');
	$redirect = __('如果您的浏览器没自动跳转，请点击这里');
	$charset = JBLOG_CHARSET;
	if ( file_exists(THEME_ROOT.'show_msg.php') ) {
		template('show_msg');
		die;
	}
	echo <<<EOT
	<html>
	<head>
		<title>$message_title</title>
		<meta http-equiv="content-type" content="text/html; charset=$charset" />
	</head>
		<body style="background:#f0f0f0;text-align:center;font-family:Verdana;">
			<div style="background:#fff;width:500px;margin:0 auto;font-size:14px;">
				<h1 style="font-size:16px;padding:8px;background:#F9FAF9;">$message_title</h1>
				<div style="text-align:left;padding:8px;">$message</div>
				<div style="padding:8px;"><a href="$jumpurl">$redirect</a></div>
			</div>
	</body>
	</html>	
EOT;
	exit();
}

//js提示框
function alert($msg, $url='') {
	$s = $url ? 'window.location="'.$url.'";' : 'history.back();';
	echo '<script type="text/javascript">alert("'.$msg.'");'.$s.'</script>';
	exit;
}

//产生随机字符串
function random($length,$string = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz') {
	$rstr = '';
	$strlen = strlen($string);
	for ($i=0; $i<$length; $i++) {
		$rstr .= $string{mt_rand(0,$strlen-1)};	
	}
	return $rstr;
}

//加载缓存
function get_cache($cachearr) {
	global $_CACHE, $cache;
	!is_array($cachearr) && $cachearr = array($cachearr);
	foreach ($cachearr as $name) {
		if ( !isset($_CACHE[$name]) ) {
			if ( !($_CACHE[$name] = $cache->get($name)) ) {
				require_once JBLOG_INC.'func_cache.php';
				recache($name);
				$_CACHE[$name] = $cache->get($name);
			}
		}
	}
}

function template($tpl, $ext = 'php') {
	extract($GLOBALS, EXTR_SKIP);
	$tpl_file = THEME_ROOT.$tpl.'.'.$ext;
	if (file_exists($tpl_file)) {
		include $tpl_file;
	} else {
		exit("template ".substr(THEME_ROOT,strlen(JBLOG_ROOT)).$tpl.'.'.$ext." not exist!");
	}
}

//输出404错误
function error_404() {
	if ( file_exists(THEME_ROOT.'404.php') ) {
		template('404');
	} else {
		header("HTTP/1.1 404 Not Found\n");
		header("Content-Type: text/html\n");
		header("Date: ".get_date('D, d M Y H:i:s',NOW)." GMT\n");
		echo '<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"><html><head><title>404 Not Found</title></head>
		<body><h1>Not Found</h1>
		<p>The requested URL '.$_SERVER['SCRIPT_NAME'].' was not found on this server.</p>
		<p>Additionally, a 404 Not Found error was encountered while trying to use an ErrorDocument to handle the request.</p></body></html>';
	}
	exit;
}


function check_blog_status() {
	$status = config('blogstatus');
	if ( defined('IN_ADMIN') || $status == 1 || is_founder() || ($status && $_USER['id']) ) return ;
	if ( $status == 2 ) {
		show_msg(__('对不起，本博客目前仅对会员开放。'), 'user.php?ac=login');
	} else {
		$message_title = __('对不起，本站目前暂停访问');
		$message = config('closereason');
		$charset = JBLOG_CHARSET;
		echo <<<EOT
		<html>
		<head>
			<title>$message_title</title>
			<meta http-equiv="content-type" content="text/html; charset=$charset" />
		</head>
			<body style="background:#f0f0f0;text-align:center;">
				<div style="background:#fff;width:500px;margin:0 auto;font-size:14px;">
					<div style="font-size:16px;font-weight:bold;padding:8px;background:#f8f8f8;border-bottom:1px solid #f0f0f0">
					$message_title
					</div>
					<div style="text-align:left;padding:8px;">$message</div>
				</div>
		</body>
		</html>
EOT;
	}
	die;
}

function my_serialize($data) {
	return add_slashes(serialize(del_slashes($data)));
}
?>